/*
 * User.h
 *
 *  Created on: 2013. 10. 4.
 *      Author: the2
 */

#ifndef USER_H_
#define USER_H_

#include <Dispatcher/Static.h>
#include <functional>

namespace FriendsServer {

//const int ONE_MON = 31;	// day
const int ONE_MON = 30;	// day
const int ONE_DAY = 86400; //sec
const int ONE_MIN = 60; // sec
const int GAME_FRIEND_MAX = 100;

class User : public ::Database::Command::IObserver
{
public:

	struct UserInfo
	{
		std::string	nickName;				// mem
		std::string	profileUrl;				// mem
		uint16_t 	gender;
		std::string birthday;
		uint16_t	isHeartBlock;
		uint16_t	isProfileBlock;
		uint16_t	isInviteBlock;
		uint16_t	isGenderOpen;			// (0:block 1:open)
		uint16_t	isBirthdayOpen;			// (0:block 1:open)
		uint32_t	lastLoginTime;
		uint32_t	unregister_time;
		uint32_t	shard_db_type;

		UserInfo() :
			gender(0),
			isHeartBlock(0),
			isProfileBlock(0),
			isInviteBlock(0),
			isGenderOpen(0),
			isBirthdayOpen(0),
			lastLoginTime(0),
			unregister_time(0),
			shard_db_type(0)
		{
			nickName.clear();
			profileUrl.clear();
			birthday.clear();
		}

		void Initialize()
		{
			gender = 0;
			isHeartBlock = 0;
			isProfileBlock = 0;
			isInviteBlock = 0;
			isGenderOpen = 0;
			isBirthdayOpen = 0;
			lastLoginTime = 0;
			unregister_time = 0;
			nickName.clear();
			profileUrl.clear();
			birthday.clear();
			shard_db_type = 0;
		}
	};

	struct FriendInfo
	{
		uint64_t	socialID;
		uint16_t	friendType;		// kakao:1 , game:2 , 요청중:3, 삭제:4, 거절:5(친구 트리에서 제거용)
		uint32_t	heartTime;
		uint32_t	buffTime;
		uint32_t	connectReqTime;
		uint32_t	friendDelTime;
		uint32_t	shard_db_type;

		FriendInfo() : socialID(0), friendType(0), heartTime(0), buffTime(0), connectReqTime(0), friendDelTime(0), shard_db_type(0)
		{
		}
	};

public:
	typedef std::map<uint32_t, FriendInfo> 				FRIENDSTREE;
	typedef std::map<uint64_t, uint32_t> 				SOCIALFRIENDSTREE;
	typedef std::map<uint32_t, uint32_t> 				DELETEFRIENDSTREE;
	typedef std::map<std::string, uint32_t> 			NOAPPTREE;
	typedef std::map<uint32_t, uint32_t> 				LASTWEEKRANKINGTREE;
	typedef std::vector<std::pair<uint32_t,uint32_t>> 	RANKINGVECTOR;
	typedef std::map<uint32_t, uint32_t>				THISWEEKFRIENDTREE;

public:
	User();
	virtual ~User();

	void 			Initialize(int channelKey);
	int				GetChannelKey() { return _channelKey; }

	virtual void 	OnResponse(::Database::Command * pCommand);
	virtual void 	OnError(::Database::Command * pCommand, const char* err, int errCode);

	void 	OnTime();
	void 	SetTimer();
	void	SetRandomTime();
	void 	KillTimer();

	time_t	GetTestInitTime(time_t curTime);
	time_t	GetWeekInitTime();

	void				SetSocialId(const uint64_t & socialid) { _socialId = socialid; }
	uint64_t			GetSocialId() { return _socialId; }

	void				SetUserSeq(const uint32_t userSeq);// { _userSeq = userSeq; }
	uint32_t			GetUserSeq() { return _userSeq; }

	void				SetRankConfirmTime(const uint32_t rankConfirmTime) { _rankConfirmTime = rankConfirmTime; }
	uint32_t			GetRankConfirmTime() { return _rankConfirmTime; }

	void				SetMyRank(const uint32_t myRank) { _myRank = myRank; }
	int32_t				GetMyRank() { return _myRank; }

	void				SetFriendRankCount(const uint32_t friendRankCount) { _friendRankCount = friendRankCount; }
	uint32_t			GetFriendRankCount() { return _friendRankCount; }

	void				SetInviteCount(const uint32_t inviteCount) { _inviteCount = inviteCount; }
	void				AddInviteCount(const uint32_t inviteCount) { _inviteCount += inviteCount; }
	uint32_t			GetInviteCount() { return _inviteCount; }

	int					SetBuffTime(const uint32_t & target_seq, const uint32_t & bufftime, const int type);
	uint32_t			GetBuffTime() { return _bufftime; }

	void				SetHeartCount(const uint32_t heartCount) { _heartCount = heartCount; }
	uint32_t			AddHeartCount(const uint32_t constCount, const uint32_t heartCount);
	uint32_t			SubtractHeartCount(const uint32_t heartCount);
	uint32_t			GetHeartCount() { return _heartCount; }

	void				SetNewsCount(const uint16_t newsCount) { _newsCount = newsCount; }
	uint16_t			GetNewsCount() { return _newsCount; }

	UserInfo 	&		GetUserInfo() { return _userInfo; }
	int					FlushUserInfo();

	int					AddFriendAndInsertDB_Kakao(const uint64_t friendSocialid, uint32_t * frUserSeq);

	int					SetGameUserSeq();
	void				SetNoAppFriends();
	int					AddInviteNoAppFriend(const std::string & socialid);

	int					SendNewsToFriend(const uint32_t & frseq, const int & type, const int & heart_count);
	int					SendNewsToFriend_Invite(const uint32_t shard_db_type, const uint32_t & frseq, const int & type, const int & heart_count);

	int					AddFriendAndInsertDB_InGame(const uint32_t frseq, const uint64_t & news_seq);


	FRIENDSTREE & 			GetFriendsTree() { return _clsFriendsTree; }
	SOCIALFRIENDSTREE & 	GetSocialFriendsTree() { return _clsSocialFriendsTree; }
	DELETEFRIENDSTREE &		GetDeleteFriendsTree() { return _clsDeleteFriendsTree; }
	NOAPPTREE	&			GetNoAppTree() { return _clsNoAppTree; }
	RANKINGVECTOR			MapGreaterSort(LASTWEEKRANKINGTREE & map);
	void					MapGreaterSort();
	LASTWEEKRANKINGTREE & 	GetRankingTree() { return _clsRankingTree; }
	RANKINGVECTOR &			GetRankingVector() { return _clsRankingVector; }

	int16_t					GetMyRanking();

	THISWEEKFRIENDTREE &	GetThisWeekFriendTree() { return _clsThisWeekFriendTree; }

	bool					GetIsAllow();

	int						DeleteFriend(const uint32_t shard_db_type, const uint32_t mySeq, const uint32_t friendSeq);

public:
	template<template <typename> class P = std::less >
	struct compare_pair_second
	{
	    template<class T1, class T2> bool operator()(const std::pair<T1,T2>&left, const std::pair<T1,T2>&right) {
	        return P<T2>()(left.second, right.second);
	    }
	};

	template <typename K>
	struct match_first
	{
	    const K _k; match_first(const K& k) : _k(k) {}
	    template <typename V>
	        bool operator()(const std::pair<K, V>& el) const
	    {
	        return _k == el.first;
	    }
	};

private:
	Dispatcher::Timer * _monitorTimer;
	uint64_t	_socialId;
	uint32_t 	_userSeq;
	uint32_t	_heartCount;
	uint32_t	_newsCount;
	uint16_t 	_isRankView;
	uint16_t 	_isRankReward;
	time_t		_rankConfirmTime;
	int32_t		_myRank;
	uint32_t	_friendRankCount;
	uint32_t	_inviteCount;
	time_t		_bufftime;
	bool		_bKilled;

	UserInfo	_userInfo;

	FRIENDSTREE			_clsFriendsTree;	// key:user seq
	SOCIALFRIENDSTREE	_clsSocialFriendsTree;	// key:social id, value:userseq(카카오친구)
	DELETEFRIENDSTREE	_clsDeleteFriendsTree;	// delete friends key:userseq , value:delete time
	NOAPPTREE			_clsNoAppTree;		// key:social id, value:inviteTime(미설치유저초대여부확인, 31 day)
	LASTWEEKRANKINGTREE _clsRankingTree;
	RANKINGVECTOR		_clsRankingVector;
	THISWEEKFRIENDTREE	_clsThisWeekFriendTree;

	int		_channelKey;
};

} /* namespace FriendsServer */
#endif /* USER_H_ */
